package com.magicode.cms.service.impl;

import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.servlet.ServletContext;

import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.InvalidPropertyException;
import org.springframework.beans.factory.annotation.Autowired;

import com.magicode.cms.common.assist.UtilPath;
import com.magicode.cms.common.assist.json.JsonOperation;
import com.magicode.cms.dao.IBaseDao;
import com.magicode.cms.entiy.base.Role;
import com.magicode.cms.entiy.base.User;
import com.magicode.cms.service.IBaseService;
import com.magicode.common.dao.PageResults;

@SuppressWarnings("rawtypes")
public abstract   class BaseServiceImpl<T extends Object ,D extends IBaseDao> implements IBaseService<T>,UtilPath{
	public List<Object> queryDataList(String hql){
		try {
			return this.getDao().queryDataList(hql, 0, 0);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			return new ArrayList<Object>();
		}
	}
	public Integer getGridPage(Map<String,String> querywhere,Long count){
		if(querywhere.isEmpty()) return 1;
		else if(!querywhere.containsKey(field_grid_size)||!querywhere.containsKey(field_grid_start)){
			return 1;
		}
		else{
			Integer start = this.getGridStartOrSize(querywhere, 0, field_grid_start);
			Integer size = this.getGridStartOrSize(querywhere, 10, field_grid_size);
			return start/size;
		}
	}
	public Integer getGridStartOrSize(Map<String,String> querywhere, Integer defaultval,String key){
		if(null ==querywhere || querywhere.isEmpty()) return defaultval;
		else if(querywhere.containsKey(key)){
			String start =  querywhere.get(key);
			return Integer.valueOf(start);
		}
		else{
			return defaultval;
		}
	}
	@Override
	public List<JsonOperation> getOpts(Map<String,Object> pram,String url,Map<String,Object> rowdata){
		return getOpts(url, rowdata.get("id").toString());
	}
	@Override
	public List<JsonOperation> getOpts(String url,String id) {
		List<JsonOperation> opts = new ArrayList<JsonOperation> ();
		JsonOperation opt= new JsonOperation();
		opt.setName("修改");
		opt.setUrl(ctx.getContextPath()+"/"+url+"/getinfo/"+id+"/edit"+url);
		opt.setType("edit");
		opts.add(opt);
		opt= new JsonOperation();
		opt.setName("删除");
		opt.setUrl(ctx.getContextPath()+"/"+url+"/"+id+"?_requestMethod=delete");
		opt.setType("delete2");
		opts.add(opt);
		return opts;
	}
	
	public Object getObject(String classname, String id) throws Exception{
		if(null!=id && !"".equals(id)){
			return this.getDao().getObject(classname, id);
		}
		return null;
	}
	
	public T getObject(String objid) throws Exception{
		if(null==objid || "".equals(objid)){
			throw new Exception(" get object but obj id is null ["+objid+"]");
		}
		Map<String ,String> where = new HashMap<String ,String>();
		where.put(field_id, objid);
		String hql = this.getHql(where);
		hql = "select "+entity_alias_name+" "+hql;
		System.out.print(hql);
		List<T> t = this.queryDataList(hql, 0, 1);
		if(null==t || t.size()==0){
			throw new Exception("not find entity by id ["+objid+"] or htl error ["+hql+"]");
		}
		return t.get(0);
	}

	public T getObject(String objid,String[] fetchJoins) throws Exception{
		if(null==objid || "".equals(objid)){
			throw new Exception(" get object but obj id is null ["+objid+"]");
		}
		Map<String ,String> where = new HashMap<String ,String>();
		where.put(field_id, objid);
		String hql = "select t "+this.getHql(where);
		String hql1 = null;
		String hql2 = null;
		if(hql.indexOf("where")!= -1){
			hql1 = hql.substring(0, hql.indexOf("where"));
			hql2 = hql.substring(hql.indexOf("where"), hql.length());
			if(fetchJoins != null){
				for(String fetchJoin : fetchJoins){
					if(fetchJoin != null){
						hql1 += " left outer join fetch "+entity_alias_name+"."+fetchJoin+" ";
					}
				}
			}
			hql = hql1 + hql2;
		}
//		如果没有条件，直接在最后的hql中添加了left join fetch
		else{
			if(fetchJoins != null){
				for(String fetchJoin : fetchJoins){
					if(fetchJoin != null){
						hql += " left outer join fetch "+entity_alias_name+"."+fetchJoin+" ";
					}
				}
			}
			
		}
		
		List<T> t = this.queryDataList(hql, 0, 1);
		if(null==t || t.size()==0){
			throw new Exception("not find entity by id ["+objid+"] or htl error ["+hql+"]");
		}
		return t.get(0);
	}
	public List<Map<String,Object>> select(Map<String,String> querywhere){
		return this.grid(querywhere);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public Boolean createObject(T obj)  {
		// TODO Auto-generated method stub
		try {
			
			Class clazz = obj.getClass();
			cleanPropertyValue(obj,clazz);
			
			  this.getDao().createObject(obj);
			  return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	/**
	 * 清除无效的属性
	 * @param obj
	 * @param clazz
	 */
	private void cleanPropertyValue(T obj, Class clazz) {
		// TODO Auto-generated method stub
		if(obj != null){
			BeanWrapperImpl bw = new BeanWrapperImpl( obj );
			Field[] fields =  clazz.getDeclaredFields();
			clazz.getSuperclass();
			for(Field field : fields){					
				ManyToOne  entityProperty = field.getAnnotation(ManyToOne.class);
				if(entityProperty != null){
	//				取到当前对象
					Object tempObject = (Object) bw.getPropertyValue(field.getName()) ; 
					if(tempObject != null){
						BeanWrapperImpl bw2 = new BeanWrapperImpl( tempObject );
		//				获得主键
						String tempObjectId = null;
						try{
//							if(bw2.isReadableProperty("id")){
//								System.out.println("can Read ID");
//							}
							tempObjectId = (String) bw2.getPropertyValue("id") ; 
						}catch(InvalidPropertyException e){
							e.printStackTrace();
							
						}
						if(tempObjectId == null || tempObjectId.trim().length() == 0){
							bw.setPropertyValue(field.getName(),null);
						}
					}
				}
			}
	//		如果有父类，清楚父类的属性
			if(clazz.getSuperclass() != null){
				cleanPropertyValue(obj , clazz.getSuperclass());
			}
		}
	}
	@SuppressWarnings("unchecked")
	public List<T> queryDataList(String hql,int start,int size){
		try {
			return this.getDao().queryDataList(hql, start, size);
		} catch (Exception e) {
			e.printStackTrace();
			// TODO Auto-generated catch block
			return new ArrayList<T>();
		}
	}
	@SuppressWarnings("unchecked")
	@Override
	public Boolean deleteObject(String objid)  {
		// TODO Auto-generated method stub
		try {
			T obj =this.getObject(objid);
			
			if(null!=obj){
				return  this.getDao().deleteObject(obj);
			}
			else{
				throw new Exception(" not find object by id ["+objid+"]");
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return false;
		}
		
	}
	
	
	@SuppressWarnings("unchecked")
	@Override
	public Boolean editObject(T obj) {
		try {
			// TODO Auto-generated method stub

			Class clazz = obj.getClass();
			cleanPropertyValue(obj,clazz);
			this.getDao().editObject(obj);
			return true;
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return false;
		}
	}
	@Override
	public List<Map<String,Object>> queryMapDataList(String hql,Map<String,String> selectprams,int start,int size){
		List<Map<String,Object>> values = new ArrayList<Map<String,Object>>();
		try {
			String selhql="";
			if(null!=selectprams&&!selectprams.isEmpty()){
				selhql=" select new Map (";
				Iterator<String> iterator =  selectprams.keySet().iterator();
				while(iterator.hasNext()){
					String key = iterator.next();
					String val = selectprams.get(key);
					selhql +=  val+","; 
				}
				selhql = selhql.substring(0, selhql.length()-1)+")";
			}
			@SuppressWarnings("unchecked")
			List<Map<String,Object>> values_ = (List<Map<String,Object>>) this.getDao().queryDataList(selhql+hql, start, size);
			return values_;
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return  values;
		}
		
	}

	//拼接查询语句
	public abstract String getHql(Map<String,String> querywhere) throws Exception;
	//grid 查询对象
	public abstract List<Map<String,Object>> grid(Map<String,String> querywhere);
	public abstract D getDao() throws Exception;
	public String getWhereOrAnd (String hql){
		return hql.contains("where")?" and " :" where ";
	}
	@Override
	public Long queryCount(Map<String,String> querywhere) {
		try {
			String hql_ = this.getHql(querywhere);
			if(null!=hql_ && !"".equals(hql_)&& hql_.contains("from")){
				String counthql = "select count("+entity_alias_name+"."+field_id+" )  "+ hql_.substring(hql_.indexOf("from"), hql_.length());
				return this.getDao().queryCount(counthql);
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return new Long(0);
	}

	@Override/**
	 * 判断登录用户是否有
	 * @param codes
	 * @return
	 */
	public boolean containRoleCodeByUser(String code,String userId){
		boolean result = false;
		try {
			String hql = " select count(t.id) "
					+ " from  "+User.class.getName()+" t , "+Role.class.getName()+" r "
					+ " where r in elements(t.roles) and t.id = :userId and r.code = :roleCode ";
			Map map = new HashMap();
			map.put("userId", userId);
			map.put("roleCode", code);
			List<Long> list = this.getDao().getCommonDaoService().queryList(hql, map);
			if(list != null && list.size() > 0){
				Long count = list.get(0);
				if(count > 0){
					result = true;
				}
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	@Autowired
	private ServletContext ctx;

	public ServletContext getCtx() {
		return ctx;
	}
	public void setCtx(ServletContext ctx) {
		this.ctx = ctx;
	}
	
	/**
	 * 将List中Map对象的byte[]字段转化为String，并返回
	 * @param resultList
	 * @param clobKey
	 * @return
	 */
	public List<Map<String, Object>> convertByteToString(
			List<Map<String, Object>> list, String clobKey) {
		List<Map<String, Object>> resultList = new ArrayList();
		for(Map map : list){
			String strValue = null;
			byte[] clobValue = (byte[]) map.get(clobKey);
			if(clobValue != null){
				try {
					strValue = new String(clobValue,"UTF-8");
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
			map.put(clobKey, strValue);
			resultList.add(map);
		}
		// TODO Auto-generated method stub
		return resultList;
	}
	/**
	 * 在列表数据中，获得一对多或多对多数据；
	 * @param hql 要求返回结果为Map，key分别为：id,title；关键字为：t ， 必须有 where条件 ，不能有order by ，如没有，加入1 = 1
	 * 例如：select new map( t.id as id , t.title as title  ) from Dictionary d , News t where d = t.type  
	 * @param connentStr
	 * @param propertyName
	 * @param pageResultList
	 * @return
	 * @throws Exception 
	 */
	public PageResults getRelateProByList(String hql , String connentStr , String propertyName , PageResults pageResultList) throws Exception{
		List list = pageResultList.getResults();
		List resultList = getRelateProByList( hql ,  connentStr ,  propertyName ,  list);
		pageResultList.setResults(resultList);
		return pageResultList;
	}
	/**
	 * 
	 * 在列表数据中，获得一对多或多对多数据；
	 * @param hql 要求返回结果为Map，key分别为：id,title；关键字为：t ， 必须有 where条件 ，不能有order by ，如没有，加入1 = 1
	 * 例如：select new map( d.id as id , t.title as title  ) from Dictionary d , News t where d = t.type  
	 * @param connentStr
	 * @param propertyName
	 * @param list
	 * @return
	 * @throws Exception 
	 */
	public List getRelateProByList(String hql , String connentStr , String propertyName , List list) throws Exception{
		String idKey = "id";
		String titleKey = "title";
//		hql = "";
		String tempHql = hql+" and t.id in (";
		
		List resultList = new ArrayList();
//		拼装Hql
		if(list != null && list.size() > 0){
			for(Object obj : list){
				String id = null;
			
				if(obj instanceof Map){
					id = (String) ((Map)obj).get("id");
				}
				else{
					BeanWrapperImpl bw = new BeanWrapperImpl( obj );
					id = (String) bw.getPropertyValue("id");
				}
				tempHql +="'"+id+"',";
			}
			tempHql = tempHql.substring(0, tempHql.length() - 1);
		}
		else{
			return list;
		}
		tempHql +=")";
		
		Map map = new HashMap();
		List<Map> mapList = this.getDao().getCommonDaoService().queryList(tempHql,map);
		if(mapList != null){
			for(Object obj : list){
				String id = null;
				
				if(obj instanceof Map){
					id = (String) ((Map)obj).get("id");
				}
				else{
					BeanWrapperImpl bw = new BeanWrapperImpl( obj );
					id = (String) bw.getPropertyValue("id");
				}
				Object propertyValue = null;
				if(connentStr != null){
					propertyValue = new String();					
					for(Map tempMap : mapList){
						String tempId = (String) tempMap.get(idKey);
						if(tempId != null && tempId.equals(id)){
							String tempTitle = (String) tempMap.get(titleKey);
							propertyValue += tempTitle+connentStr;
						}
					}
	//				截取最后一个连接字符串
					if(propertyValue != null && ((String)propertyValue).length() > 0){
						if( ((String)propertyValue).length() >  connentStr.length() ){
							propertyValue = ((String)propertyValue).substring(0, ((String)propertyValue).length() - (connentStr.length()));
						}
					}
				}
				else{
					List tempList = new ArrayList();
					for(Map tempMap : mapList){
						String tempId = (String) tempMap.get(idKey);
						if(tempId != null && tempId.equals(id)){
							tempList.add(tempMap.get(titleKey));
							
						}
					}
					propertyValue = tempList;
				}
				if(propertyName != null && propertyValue != null){
					if(obj instanceof Map){
						((Map)obj).put(propertyName, propertyValue);
					}
					else{
						BeanWrapperImpl bw = new BeanWrapperImpl( obj );
						if(bw.getPropertyType(propertyName) == List.class){
							bw.setPropertyValue(propertyName, propertyValue);
						}
						else{
							if(propertyValue instanceof List){
								if(propertyValue != null && ((List)propertyValue).size() > 0 )
								bw.setPropertyValue(propertyName, ((List)propertyValue).get(0));
							}else if(propertyValue instanceof String){
								if(propertyValue != null && !"".equals(propertyValue) )
									bw.setPropertyValue(propertyName, propertyValue);
							}
						}
					}
			}
//				bw.setPropertyValue(propertyName, propertyValue);
				resultList.add(obj);
			}
		}
		return list;
	}
}
